package com.cherry.androidcode.recyclerView

import android.util.SparseArray
import android.view.View
import androidx.annotation.CallSuper
import com.chad.library.adapter.base.BaseQuickAdapter
import com.chad.library.adapter.base.module.LoadMoreModule

/**
 * @author DongMS
 * @date 2019/6/26
 */
abstract class SelectQuickAdapter<T : ISelect, K : QuickViewHolder>(layoutResId: Int) : BaseQuickAdapter<T, K>(layoutResId), LoadMoreModule {

    //默认单选
    protected open val isMultiSelected = false

    //默认不能选择
    var isSelectState = false
        set(value) {
            field = value
            if (!field) {
                clearSelectData()
            }
            if (data.isNotEmpty()) {
                notifyDataSetChanged()
            }
        }

    //默认item整体点击
    protected open val isCompleteItemSelect = true

    private val sparseArray = SparseArray<T>()

    protected abstract val checkedViewId: Int

    override fun setNewInstance(list: MutableList<T>?) {
        clearSelectData()
        super.setNewInstance(list)
    }

    @CallSuper
    override fun convert(holder: K, item: T) {
        val position = holder.layoutPosition
        holder.setGone(checkedViewId, !isSelectState)
        holder.setCheckedAnim(checkedViewId, item.isSelected)
        if (item.isSelected) {
            sparseArray.put(position, item)
        }
        if (isCompleteItemSelect) {
            completeSelect(holder, item, position)
        } else {
            partSelect(holder, item, position)
        }
        bindData(holder, item)
    }

    //如果是checkbox可用,由于自定义的SmoothCheckBox的setOnClickListener被覆盖，所以这里局部点击使用SmoothCheckBox需要重新设置点击事件
    private fun partSelect(holder: K, item: T, position: Int) {
        holder.getView<View>(checkedViewId).setOnClickListener {
            if (isMultiSelected) {
                partMultiSelect(item, position)
            } else {
                partSingleSelect(position, item)
            }
        }
//        holder.getView<SmoothCheckBox>(checkedViewId).setOnCheckClickListener {
//            if (isMultiSelected) {
//                partMultiSelect(item, position)
//            } else {
//                partSingleSelect(position, item)
//            }
//        }
    }

    private fun partMultiSelect(item: T, position: Int) {
        item.isSelected = !item.isSelected
        if (item.isSelected) {
            sparseArray.put(position, item)
        } else {
            sparseArray.remove(position)
        }
    }

    private fun partSingleSelect(position: Int, item: T) {
        if (sparseArray.size() == 1) {
            //注意，这里的position和preSelectPosition并不是集合的真正索引
            val preSelectPosition = sparseArray.keyAt(0)
            if (preSelectPosition == position) {
                item.isSelected = false
                sparseArray.remove(position)
            } else {
                data[preSelectPosition - headerLayoutCount].isSelected = false
                val vh = recyclerView.findViewHolderForLayoutPosition(preSelectPosition) as? K
                if (vh != null) {
                    vh.setCheckedAnim(checkedViewId, false)
                } else {
                    //一些极端情况，holder被缓存在Recycler的cacheView里
                    notifyItemChanged(preSelectPosition)
                }
                item.isSelected = true
                sparseArray.clear()
                sparseArray.put(position, item)
            }
        } else if (sparseArray.size() == 0) {
            item.isSelected = true
            sparseArray.put(position, item)
        }
    }

    //需要checkedView重写OnTouchEvent return false
    private fun completeSelect(holder: K, item: T, position: Int) {
        holder.itemView.setOnClickListener {
            if (!isSelectState) {
                getOnItemClickListener()?.onItemClick(this, it, holder.layoutPosition - headerLayoutCount)
                return@setOnClickListener
            }
            if (isMultiSelected) {
                completeMultiSelect(item, holder, position)
            } else if (sparseArray.size() <= 1) {
                completeSingleSelect(position, item, holder)
            }
        }
    }

    private fun completeMultiSelect(item: T, holder: K, position: Int) {
        item.isSelected = !item.isSelected
        if (item.isSelected) {
            sparseArray.put(position, item)
        } else {
            sparseArray.remove(position)
        }
        holder.setCheckedAnim(checkedViewId, item.isSelected)
    }

    private fun completeSingleSelect(position: Int, item: T, holder: K) {
        if (sparseArray.size() == 1) {
            //注意，这里的position和preSelectPosition并不是集合的真正索引
            val preSelectPosition = sparseArray.keyAt(0)
            if (preSelectPosition == position) {
                item.isSelected = false
                sparseArray.remove(position)
                holder.setCheckedAnim(checkedViewId, false)
            } else {
                data[preSelectPosition - headerLayoutCount].isSelected = false
                val vh = recyclerView.findViewHolderForLayoutPosition(preSelectPosition) as? K
                if (vh != null) {
                    vh.setCheckedAnim(checkedViewId, false)
                } else {
                    //一些极端情况，holder被缓存在Recycler的cacheView里
                    notifyItemChanged(preSelectPosition)
                }
                item.isSelected = true
                sparseArray.clear()
                sparseArray.put(position, item)
                holder.setCheckedAnim(checkedViewId, true)
            }
        } else if (sparseArray.size() == 0) {
            item.isSelected = true
            sparseArray.put(position, item)
            holder.setCheckedAnim(checkedViewId, true)
        }
    }

    abstract fun bindData(helper: K, item: T)

    fun toggleSelect() {
        isSelectState = !isSelectState
    }

    fun getSingleSelectItem(): T? {
        if (!isSelectState) {
            return null
        }
        if (sparseArray.size() == 0) {
            return null
        }
        return sparseArray.valueAt(0)
    }

    fun getMultiSelectItem(): ArrayList<T>? {
        if (!isSelectState) {
            return null
        }
        if (sparseArray.size() == 0) {
            return null
        }
        return arrayListOf<T>().apply {
            for (index in 0 until sparseArray.size()) {
                add(sparseArray.valueAt(index))
            }
        }
    }

    fun selectAll() {
        if (!isSelectState) {
            return
        }
        repeat(data.size) {
            data[it].isSelected = true
            sparseArray.put(it + headerLayoutCount, data[it])
        }
        notifyDataSetChanged()
    }

    fun unSelectAll() {
        if (!isSelectState) {
            return
        }
        clearSelectData()
        notifyDataSetChanged()
    }

    private fun clearSelectData() {
        data.forEach { it.isSelected = false }
        sparseArray.clear()
    }

}